package org.example.java_doc_searcher_springboot.searcher;

import java.io.*;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

public class Parser {
    // 整个Parser 类的入口
    private static final String INPUT_PATH = "D:/doc_searcher_index/docs/api";
    //创建一个Index 实例
    private Index index = new Index();

    private AtomicLong t1 = new AtomicLong(0);
    private AtomicLong t2 = new AtomicLong(0);

    public void run(){
        long beg = System.currentTimeMillis();
        ArrayList<File> fileList = new ArrayList<File>();
        enumFile(INPUT_PATH,fileList);
        long endEnumFile = System.currentTimeMillis();
        System.out.println("枚举时间完毕！消耗时间："+(endEnumFile-beg)+"ms");
        for (File f : fileList) {
            System.out.println("开始解析"+f.getAbsolutePath());
            parseHTML(f);
        }
        long endFor = System.currentTimeMillis();
        System.out.println("遍历文件完毕！ 消耗时间"+(endFor-beg));

        index.save();
        long end = System.currentTimeMillis();
        System.out.println("索引制作完毕! 消耗时间："+(end-beg)+"ms");
    }
    //通过这个方法来实现"多线程制作索引"
    public void runByThread() throws InterruptedException {
        long beg = System.currentTimeMillis();
        System.out.println("索引制作开始");

        ArrayList<File> files = new ArrayList<>();
        enumFile(INPUT_PATH,files);

        CountDownLatch latch = new CountDownLatch(files.size());
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        for (File f : files) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("解析"+f.getAbsolutePath());
                    parseHTML(f);
                    latch.countDown();
                }
            });
        }

        latch.await();
        executorService.shutdown();
        index.save();
        long end = System.currentTimeMillis();
        System.out.println("索引制作完毕！"+(end-beg)+"ms");
        System.out.println("t1:"+t1 + " t2:"+t2);
    }

    private void parseHTML(File f) {
        String title = parseTitle(f);
        String url = parseUrl(f);

        long beg = System.nanoTime();
       /* String content = parseContent(f);*/
        String content = parseContentByRegex(f);
        long mid = System.nanoTime();

        index.addDoc(title,url,content);
        long end = System.nanoTime();

        t1.addAndGet(mid - beg);
        t2.addAndGet(end - mid);
    }

    public  String parseContent(File f) throws RuntimeException {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(f),1024*1024)){
            Boolean iscopy = true;

            StringBuffer content = new StringBuffer();
            while (true) {
                int ret =bufferedReader.read();
                if (ret == -1) {
                    break;
                }
                char c = (char) ret;
                if(iscopy){
                    if(c == '<'){
                        iscopy = false;
                        continue;
                    }
                    if(c == '\n' || c == '\r'){
                        c = ' ';
                    }
                    content.append(c);
                }else {
                   if(c=='>'){
                       iscopy = true;
                   }
                }
            }
            return content.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "";
    }
    private String readFile(File f) {

        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(f))) {
            StringBuilder content = new StringBuilder();
            while (true) {
                int ret = bufferedReader.read();
                if (ret == -1) {
                    break;
                }
                char c = (char) ret;
                if (c == '\n' || c == '\r') {
                    c = ' ';
                }
                content.append(c);
            }
            return content.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
    // 这个方法内部就基于正则表达式，实现去标签，以及去除script
    public String parseContentByRegex(File f){
        //1. 先把整个文件都读取到String里面
        String content = readFile(f);
        //2. 替换掉 script标签
        content = content.replaceAll("<script.*?>(.*?)</script>","");
        //3. 替换掉普通的html标签
        content = content.replaceAll("<.*?>","");
        //4. 使用正则把多个空格，合并成一个空格
        content = content.replaceAll("\\s+"," ");
        return content;
    }




    private String parseUrl(File f) {
        String part1 = "https://docs.oracle.com/en/java/javase/11/docs/api";
        String part2 = f.getAbsolutePath().substring(INPUT_PATH.length());
        return part1+part2;
    }

    private String parseTitle(File f) {
        String name = f.getName();
        return name.substring(0,name.length()-".html".length());
    }


    private void enumFile(String inputPath,ArrayList<File> fileList){
        File rootPath = new File(inputPath);
        File[] files = rootPath.listFiles();
        for(File f : files){
            if(f.isDirectory()){
                enumFile(f.getPath(),fileList);
            }else{
                if(f.getAbsolutePath().endsWith(".html")) {
                    fileList.add(f);
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {

        Parser parser = new Parser();
        /*parser.run();*/
        parser.runByThread();
    }
}

